/*-----------------------------------------------------------------------------
 * @file   hal_trng.c
 * @brief  interface for true random generator module operations
 * @author WLH<wanglehui8357@163.com> Copyright (C) 2021~2099.
-----------------------------------------------------------------------------*/
#include "hal_trng.h"
#include "board.h"
#include "dbg_tool.h"

/*-----------------------------------------------------------------------------
 * marcro define
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
 * local variable
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
 * local functions
-----------------------------------------------------------------------------*/
/**
 *@brief check whether the TRNG module is ready or not
 */
bool trng_ready_check(void)
{
    uint32_t timeout = 0;
    FlagStatus trng_flag = RESET;

    /* check wherther the random data is valid */
    do
    {
        timeout++;
        trng_flag = trng_flag_get(TRNG_FLAG_DRDY);
    } while ((RESET == trng_flag) && (0xFFFF > timeout));

    if (RESET == trng_flag)
    {
        /* ready check timeout */
        trace_error("Error: TRNG can't ready \r\n");
        trng_flag = trng_flag_get(TRNG_FLAG_CECS);
        trace_error("Clock error current status: %d \r\n", trng_flag);
        trng_flag = trng_flag_get(TRNG_FLAG_SECS);
        trace_error("Seed error current status: %d \r\n", trng_flag);
        return false;
    }
    return true;
}

/**
 *@brief configure TRNG module
 */
static bool trng_configuration(void)
{
    /* enable TRNG module clock */
    rcu_periph_clock_enable(RCU_TRNG);

    /* reset TRNG registers */
    trng_deinit();
    trng_enable();

    /* check TRNG work status */
    return trng_ready_check();
}

/**
 *@brief  get random data in range
 *@retval random data
*/
static U8 trng_random_range_get(U8 min, U8 max)
{
    if (SUCCESS == trng_ready_check())
    {
        return (trng_get_true_random_data() % (max - min + 1) + min);
    }
    return 0;
}

/*-----------------------------------------------------------------------------
 * public functions
-----------------------------------------------------------------------------*/
void hal_trng_init(void)
{
    // Initialize the TRNG hardware module
    trng_configuration();
}

U8 hal_trng_get_random(void)
{
    return trng_random_range_get(0, 255);
}
